﻿/*------------------------------------------------------------------------

PRESERVE2.HPP v3.1.9

Copyright 楊志賢 CxxlMan, 2008 - 2014
All Rights Reserved

------------------------------------------------------------------------*/
#if !defined(__PRESERVE2_HPP_CxxlMan)
#define __PRESERVE2_HPP_CxxlMan

#include "PRESERVE.HPP"

#if defined(_CXXLPRESERVE_DLLEXPORT)
#define CXXLPRESERVE_DLLEXPORT CXXL_DLLEXPORT
#else
#define CXXLPRESERVE_DLLEXPORT CXXL_DLLIMPORT
#endif


class CentralizedMgr;

namespace CxxlMan
{

class cxxlPreserve2;
class P2Smart_Ptr_Base;

template <typename T>
class P2Smart_Set;


// centralizedmgr 的再生功能用這個介面，和永緒資料的儲存容器溝通
// 每個永緒資料的子節點(非包含屬性內容的節點)映象都會經此介面相對應
class CXXLPRESERVE_DLLEXPORT IPreserve2Storage:virtual public cxxlObject
{
public:
  IPreserve2Storage()
    :cxxlObject(Spirit_Easy)
  {
  }

  virtual ~IPreserve2Storage()
  {}

  virtual UNICODE_String cxxlFASTCALL GetName() const = 0;    // 取得對應節點的名稱
  virtual UNICODE_String cxxlFASTCALL GetInterfaceID() const = 0; // 取得對應節點的 InterfaceID
  virtual UNICODE_String cxxlFASTCALL GetClassID() const = 0; // 取得對應節點的 ClassID
  virtual UNICODE_String cxxlFASTCALL GetObjID() const = 0;   // 取得對應節點的 ObjID
  virtual UNICODE_String cxxlFASTCALL GetGroup() const = 0;   // 取得對應節點的 Group
  virtual UNICODE_String cxxlFASTCALL GetSpiritStr() const = 0;  // 取得對應節點的 Spirit

  virtual bool isEmpty() const = 0;                    // 是空資料嗎(無子節點也無內容)
  virtual void ResetFirst() const = 0;                 // 重置子節點序列至第一個位置
  virtual bool haveSetCount() const = 0;               // 檢查還有沒有子節點子集
  virtual unsigned long GetSetCount() const = 0; // 取得子節點子集數量
  virtual Smart_Ptr<IPreserve2Storage> cxxlFASTCALL GetIPreserve2StorageNext() const = 0;  // 取得下一個子節點的對應的 IPreserve2Storage 介面

  virtual bool cxxlFASTCALL Load(const Smart_Ptr<cxxlPreserve> &v) const = 0; // 為此節點相對應的 cxxlPreserve 物件，做永續資料的取回動作(只做這一層不包含子物件)
};


class CXXLPRESERVE_DLLEXPORT cxxlPreserve2:virtual protected cxxlPreserve
{
  // 延伸自 class IcxxlObject
  void cxxlFASTCALL YanLuoWang_ChkIn();
  void cxxlFASTCALL YanLuoWang_ChkOut();

  UNICODE_String InterfaceID; // 經由 cxxlCM_GetElement() 產生物件後會將 cxxlCM_GetElement() 的 ClassID 參數記錄於此
  UNICODE_String ClassID; // 定義 介面/實作 的 class 識別
  UNICODE_String ObjID; // 若經由 CentralizedMgr 產生會會賦予 UUID
  UNICODE_String Group; // 記錄 cxxlCM_GetElement() 取得 dll 所採用的 Group

  wchar_t *InterfaceID_bp;
  wchar_t *ClassID_bp;
  wchar_t *ObjID_bp;
  wchar_t *Group_bp;
  wchar_t *Spirit_bp;

  void * cxxlFASTCALL GetPreserve2() const
  {
    return (void*)this;
  }

  void cxxlFASTCALL SetInterfaceID(const UNICODE_String &ID)
  {
    InterfaceID = ID;
  }

  void cxxlFASTCALL SetObjID(const UNICODE_String &ID)
  {
    ObjID = ID;
  }

  void cxxlFASTCALL SetGroup(const UNICODE_String &group)
  {
    Group = group;
  }

  UNICODE_String cxxlFASTCALL GetObjID() const
  {
    return ObjID;
  }

  UNICODE_String cxxlFASTCALL GetClassID() const
  {
    return ClassID;
  }

  UNICODE_String cxxlFASTCALL GetGroup() const
  {
    return Group;
  }

protected:
  // 儲存容器藉此取得要永續存取的屬性資料
  // 延伸類別須以 virtual 的形式覆寫
  // 並且須呼叫上層類別的此函數
  virtual bool cxxlFASTCALL Ref(Filter *F);


public:
  // Constructor
  cxxlPreserve2(const UNICODE_String &ClassId_Arg)
    :cxxlObject(Spirit_Easy)
  {
    ClassID = ClassId_Arg;
  }

  // Destructor
  virtual ~cxxlPreserve2()
  {

  }

  friend class Smart_Ptr<cxxlPreserve2>;
  friend class P2Smart_Ptr_Base;

  template <typename T, bool isUnique>
  friend class SList;

  template <typename T>
  friend class P2Smart_Set;

  friend class ::CentralizedMgr;
  friend class IPreserve2Storage;
};


class P2Smart_Ptr_Base:public Smart_Ptr<cxxlPreserve2>, public _Sets
{

protected:
  Smart_Ptr<cxxlList<cxxlPreserve> > cxxlFASTCALL GetPreserveList(cxxlPreserve2 *pObj) const
  {
    Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = new cxxlList<cxxlPreserve>;
    if(pObj)
      cxxlPreserve_List->Push_Back(pObj);
    return cxxlPreserve_List;
  }

  void cxxlFASTCALL SetToSmartPtr(cxxlPreserve2 *pObj)
  {
    Smart_Ptr<cxxlPreserve2>::operator =(pObj);
  }


protected:
  P2Smart_Ptr_Base(cxxlPreserve2 *pObj,cxxlPreserve2 *Host,const UNICODE_String &Name_Arg)
    :Smart_Ptr(pObj, Host), _Sets(Host, Name_Arg)
  {

  }

public:

};

/*
** 只能作為 cxxlPreserve2 的成員函數之用
*/
template <typename T>
class P2Smart_Ptr:public P2Smart_Ptr_Base
{
  T *m_pObj;

  virtual Smart_Ptr<cxxlList<cxxlPreserve> > cxxlFASTCALL GetPreserveList() const
  {
    return P2Smart_Ptr_Base::GetPreserveList(m_pObj);
  }

  virtual REGENERARETURN_TYPE cxxlFASTCALL PutPreserve2(const Smart_Ptr<cxxlPreserve2> &Preserve2_Arg)
  {
    Smart_Ptr<T> temp_Ptr = Smart_Cast<T>(Preserve2_Arg);
    if(temp_Ptr.isNULL() == false)
    {
      *this = temp_Ptr;
      return Regenera_Success;
    }
    else
      return Regenera_NotMatchP2Smart_Ptr;
  }

  virtual REGENERARETURN_TYPE cxxlFASTCALL PutEmptyPreserve2()
  {
    (*this).Destroy();
    return Regenera_Success;
  }

public:
  // Destructor
  virtual ~P2Smart_Ptr()
  {
  }

  // Constructor
  P2Smart_Ptr(T *pObj,cxxlPreserve2 *Host,const UNICODE_String &Name_Arg)
    :P2Smart_Ptr_Base(pObj, Host, Name_Arg)
  {
    m_pObj = pObj;
  }

  // 設定函數
  P2Smart_Ptr &cxxlFASTCALL operator=(T *pObj)
  {
    m_pObj = pObj;
    SetToSmartPtr(pObj);
    return *this;
  }

  // Copy 函數
  P2Smart_Ptr &cxxlFASTCALL operator=(const P2Smart_Ptr &Src)
  {
    m_pObj = Src.m_pObj;
    SetToSmartPtr(Src.m_pObj);
    return *this;
  }

  T *cxxlFASTCALL operator->() const
  {
    return m_pObj;
  }

  cxxlFASTCALL operator T*() const
  {
    return m_pObj;
  }

  // 放棄持有的物件(包裹的物件成為 NULL)
  void cxxlFASTCALL Destroy()
  {
    Smart_Ptr<cxxlPreserve2>::Destroy();
    m_pObj = NULL;
  }


};





/*
** 只能作為 cxxlPreserve2 的成員函數之用
*/
template <typename T>
class P2Smart_Set:private Smart_Ptr<cxxlObject>, public _Sets
{

  SList<T,false> *m_pSetList;

  virtual Smart_Ptr<cxxlList<cxxlPreserve> > cxxlFASTCALL GetPreserveList() const
  {
    Smart_Ptr<cxxlList<cxxlPreserve> > cxxlPreserve_List = new cxxlList<cxxlPreserve>;

    Smart_Ptr<cxxlList<T> > tmp_List = m_pSetList->cxxlList_Create();
    tmp_List->ResetPT(toHead);
    unsigned long Count = tmp_List->GetCount();
    for(Smart_Ptr<T> tmp_Ptr = (*tmp_List)++; Count; --Count,tmp_Ptr = (*tmp_List)++)
      cxxlPreserve_List->Push_Back((cxxlPreserve2*)(T*)tmp_Ptr);

    return cxxlPreserve_List;
  }

  virtual REGENERARETURN_TYPE cxxlFASTCALL PutPreserve2(const Smart_Ptr<cxxlPreserve2> &Preserve2_Arg)
  {
    Smart_Ptr<T> temp_Ptr = Smart_Cast<T>( Preserve2_Arg );
    if(temp_Ptr.isNULL() == false)
    {
      m_pSetList->Push_Back(temp_Ptr);
      return Regenera_Success;
    }
    else
      return Regenera_NotMatchP2Smart_Ptr;
  }

  virtual REGENERARETURN_TYPE cxxlFASTCALL PutEmptyPreserve2()
  {
    m_pSetList->Push_Back(NULL);
    return Regenera_Success;
  }



public:
  // Destructor
  virtual ~P2Smart_Set()
  {
    delete m_pSetList;
  }

  // Constructor
  P2Smart_Set(cxxlPreserve2 *Host,const UNICODE_String &Name_Arg)
    :Smart_Ptr<cxxlObject>((m_pSetList = new SList<T,false>), Host),
     _Sets(Host, Name_Arg)
  {
    m_pSetList = new SList<T,false>;
  }

  // 加入一個子物件
  void cxxlFASTCALL Add(const Smart_Ptr<T> &addObj)
  {
    m_pSetList->Push_Back(addObj);
  }

  // 移除指定的子物件
  void cxxlFASTCALL Delete(const Smart_Ptr<T> &delObj)
  {
    m_pSetList->Delete(delObj);
  }

  // 取得所有子物件
  Smart_Ptr<cxxlList<T> > cxxlFASTCALL GetList() const
  {
    return m_pSetList->cxxlList_Create();
  }

  // 取得子物件的數目
  unsigned long cxxlFASTCALL GetCount() const
  {
    return m_pSetList->GetCount();
  }

  // 放棄所有的物件
  void cxxlFASTCALL Destroy()
  {
    m_pSetList->ClearAll();
  }

};


CXXLPRESERVE_DLLEXPORT cxxlPreserve2 * cxxlFASTCALL _Preserve2_Cast(const Smart_Ptr<cxxlObject> &Src);

template <typename T>
Smart_Ptr<T> cxxlFASTCALL Preserve2_Cast(const Smart_Ptr<cxxlObject> &Src)
{
  return Smart_Cast<T>(Smart_Ptr<cxxlPreserve2>( (cxxlPreserve2*)_Preserve2_Cast(Src) ));
}



}   /* namespace CxxlMan */
#endif
